Head First Python 学习笔记-Chapter4:持久化--将数据写入文件

第四章主要涉及文件的写入,包括使用with语句、pickle处理文件等。

简单文件写入

1
2
3
>>> out = open('data.out', 'w') # 以w模式打开,在写入前会清空文件
>>> print("测试一下",file=out)
>>> out.close() # 一定要进行close,即刷新输出

可以看到在当前工作目录下生成了一个data.out文件,内容为:测试一下。

当尝试往一个不存在的文件写入时,程序首先会创建一个新文件。

读取/写入文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
man = []
other = []
try:
data = open('sketch.txt')
for each_line in data:
try:
(role, line_spoken) = each_line.split(':', 1)
line_spoken = line_spoken.strip() # 去除字符串中的首尾空字符
if role == 'Man':
man.append(line_spoken)
elif role == 'Other Man':
other.append(line_spoken)
except:
pass
data.close()
except:
print('文件不存在!')

try:
man_file = open('man_data.txt','w')
other_file = open('other_data.txt','w')
print(man,file=man_file)
print(other,file=other_file)

man_file.close()
other_file.close()
except IOError:
print('文件异常')

使用with处理文件异常

  • 通常的try/expect/finally方式:
1
2
3
4
5
6
7
8
try:
data = data = open('missing', 'w')
print(data.readline(), end='')
except IOError as err:
print('File error' + str(err))
finally:
if 'data' in locals():
data.close()
  • 使用with进行处理:
1
2
3
4
5
try:
with open('missing', 'w') as data:
print("It's...", file=data)
except IOError as err:
print('File error' + str(err))

with语句利用了一种名为上下文管理协议(context management protocol)的python技术。

使用with时,不再需要操心关闭打开的文件,因为python解释器会自动的进行。

pickle

可以保存和加载几乎任何Python数据对象,包括列表。
使用pickle很简单,只需要导入所需的模块,然后使用dump()保存数据,以后再某个时间点可以使用load()来恢复数据。但是这些操作的一个要求就是必须要以二进制访问模式打开这些文件。出现异常时,pickle会产生一个PickleError类型的异常。

1
2
3
4
5
6
7
import pickle # 一定要导入pickle模块

with open('mydata.pickle', 'wb') as mysavadata: #b代表使用二进制模式打开文件
pickle.dump([1, 2, 'three'], mysavadata) # 使用dump保存数据文件
with open('mydata.pickle', 'rb') as myrestoredata:
a_list = pickle.load(myrestoredata) # 使用load从文件恢复数据
print(a_list)

知识点

open()函数

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None):打开一个文件并返回对应的文件对象,若文件不存在,将抛出OSError异常。

主要参数:

  • file:可以是一个代表文件路径(绝对路径或者相对路径)字符串或者一个包装好的文件对象
  • mode:可选,用以指定文件打开的模式,分为以下几种:
字符 含义
r 只读(默认)
w 只写,并且先将文件清空
x 创建新文件并写入, 若文件已存在则会失败
a 只写,将写入的内容添加到已有内容的后面
b 二进制模式
t 文本模式(默认)
+ 打开硬盘文件用于更新(读和写)

str.strip([chars])函数

没有参数则清除首尾的空白字符,有参数(比如a),怎将首尾中的a全部清除,直到不是a的字符,如:

1
2
3
4
>>> '   spacious   '.strip()
'spacious'
>>> 'www.example.com'.strip('cmowz.')
'example'

locals():返回当前作用域中的变量集合

当一行代码要使用变量x的值时,Python会到所有可用的名字空间去查找变量,按照如下顺序:

  • 局部名字空间:特指当前函数或类的方法。如果函数定义了一个局部变量x,Python将使用这个变量,然后停止搜索。
  • 全局名字空间:特指当前的模块。如果模块定义了一个名为x的变量,函数或类,Python将使用这个变量然后停止搜索。
  • 内置名字空间:对每个模块都是全局的。作为最后的尝试,Python将假设x是内置函数或变量。

如果Python在这些名字空间找不到x它将放弃查找并引发一个NameError的异常,同时传递There is no variable named 'x'这样一条信息。

象Python中的许多事情一样,名字空间在运行时直接可以访问。特别地,局部名字空间可以通过内置的locals函数来访问。全局(模块级别)名字空间可以通过globals函数来访问。

str()函数

返回对象的string类型,str(object)将调用object.__str__(),类似于Java中的toString()方法

with语句

有一些任务,可能事先需要设置,事后做清理工作。对于这种场景,Python的with语句提供了一种非常方便的处理方式。一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

如果不用with语句,代码如下:

1
2
3
file = open("/tmp/foo.txt")
data = file.read()
file.close()

这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。下面是处理异常的加强版本:

1
2
3
4
5
file = open("/tmp/foo.txt")
try:
data = file.read()
finally:
file.close()

虽然这段代码运行良好,但是太冗长了。这时候就是with一展身手的时候了。除了有更优雅的语法,with还可以很好的处理上下文环境产生的异常。下面是with版本的代码:

1
2
with open("/tmp/foo.txt") as file:
data = file.read()

if/elif

1
2
3
4
if role == 'Man':
man.append(line_spoken)
elif role == 'Other Man': # elif相当于 else if
other.append(line_spoken)
hoxis wechat
一个脱离了高级趣味的程序员,关注回复1024有惊喜~
赞赏一杯咖啡
0%